﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SploreClient
{
    public class Client
    {
        #region ClientState Plumbing
        private enum ClientState
        {
            Underflow,
            Unknown,
            Done,
            Initialize,
            Title,
            Login,
            ConfirmQuit,
            Quit,
        }
        private delegate void ClientStateHandler();
        private Dictionary<ClientState, ClientStateHandler> stateTable = new Dictionary<ClientState,ClientStateHandler>();
        private Stack<ClientState> stateStack = new Stack<ClientState>();
        private void PushAndSetCurrentState(ClientState theClientState)
        {
            stateStack.Push(theClientState);
        }
        private void PushCurrentState()
        {
            PushAndSetCurrentState(ClientState.Unknown);
        }
        private void PopCurrentState()
        {
            if (stateStack.Count > 0)
            {
                stateStack.Pop();
            }
        }
        private ClientState CurrentState
        {
            get
            {
                if (stateStack.Count != 0)
                {
                    return stateStack.Peek();
                }
                else
                {
                    return ClientState.Underflow;
                }
            }
            set
            {
                if (stateStack.Count == 0)
                {
                    stateStack.Push(value);
                }
                else
                {
                    stateStack.Pop();
                    stateStack.Push(value);
                }
            }
        }
        #endregion
        #region Service Reference Clients
        private Session.SessionClient sessionClient = null;
        private Session.SessionClient SessionClient
        {
            get
            {
                if (sessionClient == null)
                {
                    try
                    {
                        sessionClient = new Session.SessionClient();
                    }
                    catch
                    {
                        sessionClient = null;
                    }
                }
                return sessionClient;
            }
        }
        #endregion
        #region Constructor
        public Client()
        {
            stateTable.Add(ClientState.Initialize, InitializeStateHandler);
            stateTable.Add(ClientState.Title, TitleStateHandler);
            stateTable.Add(ClientState.Login, LoginStateHandler);
            stateTable.Add(ClientState.ConfirmQuit, ConfirmQuitStateHandler);
            stateTable.Add(ClientState.Quit, QuitStateHandler);
        }
        #endregion
        #region Execution of Engine
        public void Run()
        {
            Run(ClientState.Initialize);
        }
        private void Run(ClientState theInitialState)
        {
            stateStack.Clear();
            CurrentState = theInitialState;
            while (CurrentState != ClientState.Done)
            {
                if (stateTable.ContainsKey(CurrentState))
                {
                    stateTable[CurrentState]();
                }
                else
                {
                    UnknownStateHandler();
                }
            }
        }
        #endregion
        #region ClientStates
        #region UnknownHandler
        private void UnknownStateHandler()
        {
            Conio.RenderTitleLine(Resources.States.Unknown.Title);
            Conio.RenderContentLine(Resources.States.Unknown.ContentFormat,CurrentState.ToString());
            Conio.AnyKeyPromptLine(Resources.States.Common.PressAnyKey);
            CurrentState = ClientState.Done;
        }
        #endregion
        #region InitializeHandler
        private void InitializeStateHandler()
        {
            Conio.Initialize();
            CurrentState = ClientState.Title;
        }
        #endregion
        #region TitleHandler
        private void TitleStateHandler()
        {
            Conio.RenderNewLine();
            Conio.RenderTitleLine(Resources.States.Title.ApplicationTitle);
            Conio.RenderContentLine(Resources.States.Title.Content);
            Conio.RenderMenuLine(Resources.States.Title.LoginMenuItem);
            Conio.RenderMenuLine(Resources.States.Title.QuitMenuItem);
            HashSet<string> keys = new HashSet<string>();
            keys.Add(Resources.Hotkeys.Title.LoginMenuItem);
            keys.Add(Resources.Hotkeys.Title.QuitMenuItem);
            string input = Conio.ReadFilteredKey(keys);
            if (input == Resources.Hotkeys.Title.LoginMenuItem)
            {
                CurrentState = ClientState.Login;
            }
            else
            {
                CurrentState = ClientState.ConfirmQuit;
            }
        }
        #endregion
        #region LoginHandler
        private void LoginStateHandler()
        {
            Conio.RenderNewLine();
            Conio.RenderTitleLine(Resources.States.Login.Title);
            Conio.RenderContentLine(Resources.States.Login.EnterUserName);
            string theUserName = Conio.ReadLine();
            Conio.RenderContentLine(Resources.States.Login.EnterPassword);
            string thePassword = Conio.ReadLine();
            Session.ResultPackageOfSessionTokenPdwhsISG sessionResult = SessionClient.OpenSession(theUserName, thePassword);
            SessionClient.CloseSession(sessionResult.Package);
            CurrentState = ClientState.Title;
        }
        #endregion
        #region ConfirmQuitHandler
        private void ConfirmQuitStateHandler()
        {
            Conio.RenderNewLine();
            Conio.RenderTitleLine(Resources.States.ConfirmQuit.Title);
            Conio.RenderContentLine(Resources.States.ConfirmQuit.Content);
            Conio.RenderMenuLine(Resources.States.Common.YesMenuItem);
            Conio.RenderMenuLine(Resources.States.Common.NoMenuItem);
            HashSet<string> keys = new HashSet<string>();
            keys.Add(Resources.Hotkeys.Common.NoMenuItem);
            keys.Add(Resources.Hotkeys.Common.YesMenuItem);
            string input = Conio.ReadFilteredKey(keys);
            if (input == Resources.Hotkeys.Common.NoMenuItem)
            {
                CurrentState = ClientState.Title;
            }
            else
            {
                CurrentState = ClientState.Quit;
            }
        }
        #endregion
        #region QuitHandler
        private void QuitStateHandler()
        {
            Conio.RenderNewLine();
            Conio.RenderTitleLine(Resources.States.Quit.Title);
            CurrentState = ClientState.Done;
        }
        #endregion
        #endregion
    }
}
